<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo</title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }

        html, body {
            overflow-x: hidden;
            overflow-y: auto;
            height: 100%;
            width: 100%;
        }

        .canvas-frame {
            height: 100%;
            min-height: 400px;
            width: 100%;
            border: none;
            cursor: pointer;
            background-color: #EEEEEE;
        }
    </style>
    <script src="js/three.js?t=1"></script>
    <!--浏览器支持检测-->
    <script src="utils/Detector.js"></script>
    <!--监控控件-->
    <script src="utils/stats.js"></script>
    <!--运动-->
    <script src="utils/tween.js"></script>
    <!--时钟材质-->
    <script src="utils/clock.js?t=2"></script>
    <!--鼠标控制摄像机-->
    <script src="utils/OrbitControls.js"></script>
    <!--颜色定义-->
    <script src="utils/color.js"></script>
    <!--拖拽对象-->
    <script src="utils/DragControls.js"></script>
</head>
<body>
<div id="canvas-frame" class="canvas-frame"></div>
<script>

    (function threeJsSupportCheck() {
        if (!Detector.webgl) {
            Detector.addGetWebGLMessage();
        }
    })();

    function getShowWidth() {
        return Math.max(window.innerWidth, 225)
    }

    function getShowHeight() {
        return Math.max(window.innerHeight, 400)
    }

    let width = getShowWidth();
    let height = getShowHeight();
    clock();

    // 舞台*
    let scene;

    function initScene() {
        scene = new THREE.Scene();
        scene.name = 'SCENE';
    }


    // 光源*
    let lightValue = 1;
    let light1;
    let light2;
    let light3;

    let lightHighIntensity = 1;
    let lightLowIntensity = 0.4;

    function getAmbientLightIntensity() {
        return Math.min(Math.max(lightLowIntensity, lightValue), lightHighIntensity) * 3 / 4;
    }

    function getPointLightIntensity() {
        return Math.min(Math.max(0, lightValue / 5), 0.2);
    }

    function getDirectionalLightIntensity() {
        return Math.min(Math.max(lightLowIntensity, lightValue), lightHighIntensity) / 4;
    }

    function initLight() {
        // 这4种可以产生阴影：DirectionalLight、PointLight、RectAreaLight、SpotLight。
        //现只会SpotLight，PointLight可以在有其他平行环境光时，制造比较清晰的阴影
        // 光，会影响MeshLambertMaterial和MeshPhongMaterial材质
        light1 = new THREE.AmbientLight(0xffffff, getAmbientLightIntensity());//环境光。让物体变亮
        scene.add(light1);
        light2 = new THREE.PointLight(0xffffff, getPointLightIntensity());//点光。此处仅造阴影用，值大了会让方块变色严重
        light2.position.set(50, 100, 50);
        light2.castShadow = true;
        //设置阴影分辨率
        light2.shadow.mapSize.width = 1024;
        light2.shadow.mapSize.height = 1024;
        scene.add(light2);
        light3 = new THREE.DirectionalLight(0xffffff, getDirectionalLightIntensity());//平行光。制造明暗面，并不使方块变色严重
        light3.position.set(50, 50, 50);
        scene.add(light3);
    }

    let circle = {
        radius: 50,
        centerPoint: {
            x: 0, y: 0
        },
        degree: 0,
    };

    function getSunPosition() {
        let x = circle.centerPoint.x + Math.cos(Math.PI * 2 / 360 * circle.degree) * circle.radius;
        let y = circle.centerPoint.y + Math.sin(Math.PI * 2 / 360 * circle.degree) * circle.radius;
        return {x, y}
    }

    // 相机*
    let camera;
    let controls;

    function initCamera() {
        camera = new THREE.PerspectiveCamera(45, getShowWidth() / getShowHeight(), 0.01, 1e10);
        camera.name = "CAMERA";
        //使用TrackballControls不能设置相机位置
        camera.position.x = 30;
        camera.position.y = 30;
        camera.position.z = 30;

        //会使坐标系中此向量在屏幕中，显示为竖直向上
        // camera.up.x = 0;
        // camera.up.y = 1;
        // camera.up.z = 0;
        camera.lookAt(0, 0, 0);
        controls = new THREE.OrbitControls(camera);
        // 如果使用animate方法时，将此函数删除
        //controls.addEventListener( 'change', render ,false);
        // 使动画循环使用时阻尼或自转 意思是否有惯性
        controls.enableDamping = true;
        //动态阻尼系数 就是鼠标拖拽旋转灵敏度
        controls.dampingFactor = 1.5;
    }

    // 渲染器*
    let renderer;

    function initRenderer() {
        renderer = new THREE.WebGLRenderer({
            antialias: true
        });
        renderer.name = 'RENDERER';
        renderer.shadowMap.enabled = true;
        renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        renderer.setSize(getShowWidth(), getShowHeight());
        document.getElementById('canvas-frame').appendChild(renderer.domElement);
        renderer.setClearColor(0xFFFFFF, 1.0);//背景颜色
    }

    // 查看信息小控件
    let stats;

    function initStats() {
        stats = new Stats();
        stats.domElement.style.position = 'absolute';
        stats.domElement.style.left = '0px';
        stats.domElement.style.top = '0px';
        document.getElementById('canvas-frame').appendChild(stats.domElement);
    }


    //使渲染器与相机随窗口大小改变适应。自适应窗口大小
    window.onresize = function () {
        //更新相机视角比例
        camera.aspect = getShowWidth() / getShowHeight();
        camera.updateProjectionMatrix();
        renderer.setSize(getShowWidth(), getShowHeight());
    };

</script>
<script>
    //--------------------------------------点击事件--------------------------------------start
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();

    //获取点击的对象
    function getClickedObject(event) {
        //通过鼠标点击的位置计算出raycaster所需要的点的位置，以屏幕中心为原点，值的范围为-1到1.
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
        // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
        raycaster.setFromCamera(mouse, camera);
        // 获取raycaster直线和所有模型相交的数组集合
        return raycaster.intersectObjects(scene.children);
    }

    //点击的对象
    let objForMouseDown = null;

    function addObjForMouseDown(obj) {
        // let material = new THREE.MeshBasicMaterial({color: 0xff0000});
        // objForMouseDown = new THREE.Mesh( obj.geometry, material);//无光照效果，有颜色
        objForMouseDown = obj.clone();
        scene.add(objForMouseDown);
    }

    function deleteObjForMouseDown() {
        scene.remove(objForMouseDown);
    }

    //按键按下事件
    function mouseDown(event) {
        let objects = getClickedObject(event);
        if (objects.length > 0) {
            let obj = objects[0].object;
            console.log("点击的对象：" + obj.name, obj)
            addObjForMouseDown(obj);
        }
    }

    //按键抬起事件
    function mouseUp(event) {
        deleteObjForMouseDown()
    }

    //监听事件
    window.addEventListener('mousedown', mouseDown, false);
    window.addEventListener('mouseup', mouseUp, false);


    //给对象设置拖动事件
    function setDragFunction(obj, changeColorWhenDragging) {
        let dragControls = new THREE.DragControls([obj], camera, renderer.domElement);
        dragControls.addEventListener('dragstart', function (event) {
            controls.enabled = false;
        }, false);
        dragControls.addEventListener('dragend', function (event) {
            controls.enabled = true;
        }, false);
    }

    //--------------------------------------点击事件--------------------------------------end
</script>
<script>


    // 初始化基本控件
    initScene();//舞台*
    initCamera();//相机*
    initRenderer();//渲染器*
    initLight();//光源*
    initStats();//监控控件

</script>
<script>
    //--------------------------------------动作代码------------------------------------------
    //运动
    function actionMove(obj, actions) {
        let x = obj.position.x;
        let y = obj.position.y;
        let z = obj.position.z;
        let firstTween;
        let oldTween;
        for (let i in actions) {
            actions[i].properties.x = x + actions[i].properties.x;
            actions[i].properties.y = y + actions[i].properties.y;
            actions[i].properties.z = z + actions[i].properties.z;
            let newTween = new TWEEN.Tween(obj.position)
                .to(actions[i].properties, actions[i].duration || 1000)
                .easing(actions[i].easing)
            if (oldTween !== undefined) {
                oldTween.chain(newTween);
            }
            if (i === '0') {
                firstTween = newTween;
            }
            oldTween = newTween;
        }
        oldTween.chain(firstTween)
        return firstTween;
        // .to( { x: -4}, 3000 ).repeat( Infinity ).start();
    }

    let actions1 = [
        {
            properties: {
                x: 5, y: 0, z: 0
            },
            easing: TWEEN.Easing.Cubic.In
        }, {
            properties: {
                x: 0, y: 5, z: 0
            },
            easing: TWEEN.Easing.Exponential.InOut
        }, {
            properties: {
                x: 0, y: 0, z: 5
            },
            easing: TWEEN.Easing.Elastic.Out
        }
    ];

    //旋转
    function actionRotate(obj, x, y, z) {
        if (Array.isArray(obj)) {
            for (let e of obj) {
                e.rotation.x += x || 0;
                e.rotation.y += y || 0;
                e.rotation.z += z || 0;
            }
        } else {
            obj.geometry.needsUpdate = true;
            // texture4.needsUpdate=true;
            obj.rotation.x += x || 0;
            obj.rotation.y += y || 0;
            obj.rotation.z += z || 0;
        }
    }

    //旋转(三方向同速)
    function actionRotateXYZ(obj, xyz) {
        actionRotate(obj, xyz || 0.01, xyz || 0.01, xyz || 0.01)
    }

</script>
<script>
    //-----------以下为物体添加代码---------------------------------------------------------------
    function addLine(x1, y1, z1, x2, y2, z2, color) {
        x1 = x1 || 0;
        y1 = y1 || 0;
        z1 = z1 || 0;
        x2 = x2 || 0;
        y2 = y2 || 0;
        z2 = z2 || 0;
        color = color || 0xff0000;
        let startPoint = new THREE.Vector3(x1, y1, z1);
        let endPoint = new THREE.Vector3(x2, y2, z2);
        let geometry = new THREE.Geometry();
        geometry.vertices.push(startPoint);
        geometry.vertices.push(endPoint);
        let material = new THREE.MeshBasicMaterial({color: color});
        let line = new THREE.LineSegments(geometry, material, THREE.LinePieces);
        //  return line;
        scene.add(line);
    }

    // 网格
    function addLines() {
        const gridSize = 100;
        const lineWidth = 4;
        for (let i = 0; i <= gridSize * 2 / lineWidth; i++) {

            let geometry = new THREE.Geometry();
            geometry.vertices.push(new THREE.Vector3(-gridSize, 0, 0));
            geometry.vertices.push(new THREE.Vector3(gridSize, 0, 0));

            let lineX = new THREE.Line(geometry, new THREE.LineBasicMaterial({color: 0xcccccc, opacity: 0.2}));
            lineX.position.z = (i * lineWidth) - gridSize;
            scene.add(lineX);

            let lineY = new THREE.Line(geometry, new THREE.LineBasicMaterial({color: 0xcccccc, opacity: 0.2}));
            lineY.position.x = (i * lineWidth) - gridSize;
            lineY.rotation.y = 90 * Math.PI / 180;   //  旋转90度
            scene.add(lineY);

            // let lineZ = new THREE.Line(geometry, new THREE.LineBasicMaterial({color: 0x0000ff, opacity: 0.5}));
            // lineZ.position.x = (i * 4)-gridSize/2 ;
            // lineZ.rotation.z = 90 * Math.PI / 180;   //  旋转90度
            // scene.add(lineZ);
        }
    }

    addLine(0, 0, 0, 10, 0, 0, 0xff0000);//中心坐标线，X轴，红
    addLine(0, 0, 0, 0, 10, 0, 0x00ff00);//中心坐标线，Y轴，绿
    addLine(0, 0, 0, 0, 0, 10, 0x0000ff);//中心坐标线，Z轴，蓝
    addLines();

    function addBasePlane() {
        let geometry = new THREE.PlaneGeometry(200, 200, 1, 1);
        let material = new THREE.MeshLambertMaterial({color: 0xffffff});
        let basePlaneMesh = new THREE.Mesh(geometry, material);
        basePlaneMesh.rotation.x = -0.5 * Math.PI;
        basePlaneMesh.position.y = -0.1;
        basePlaneMesh.receiveShadow = true;
        scene.add(basePlaneMesh);
        return basePlaneMesh;
    }

    addBasePlane();

    //面颜色素材
    function canvasTexture(rgbaColor, imgSrc) {
        let canvas = document.createElement('canvas');
        canvas.width = 256;
        canvas.height = 256;
        let context = canvas.getContext('2d');
        if (context) {
            if (rgbaColor) {
                context.fillStyle = 'rgba(0,0,0,1)';
                context.fillRect(0, 0, 256, 256);
                context.rect(16, 16, 224, 224);
                context.lineJoin = 'round';
                context.lineWidth = 16;
                context.fillStyle = rgbaColor;
                context.strokeStyle = rgbaColor;
                context.stroke();
                context.fill();
            }
            if (imgSrc) {
                let image = new Image();
                image.src = imgSrc;
                image.onload = function () {
                    context.drawImage(image, 0, 0);
                    ////遍历像素并修改rgba值
                    // let imgData = context.getImageData(0, 0, 256, 256);//我这个图片大小是 256 * 256 ,这里指从（0, 0）获取宽256高256的像素的data
                    // let data = imgData.data;//每个像素的data是个数组（红，绿，蓝，透明度）
                    // //遍历每个像素
                    // for (let i = 0; i < data.length; i += 4) {
                    //     // data[i] = 255 - data[i];
                    //     data[i + 1] = data[i + 1]+10;
                    //     // data[i + 2] = 255 - data[i + 2];
                    //     //这里只反转颜色，不管透明度
                    // }
                    // //在指定位置输出图片
                    // context.putImageData(imgData, 0, 0);//在（0,0）的位置放上我的新图片
                };
            }
        } else {
            alert('您的浏览器不支持Canvas')
        }
        return canvas;
    }

    function buildSimpleCubeForRubikCube(len, x, y, z, cubeIndex) {
        let simpleCube;
        len = len || 5;
        x = x || 0;
        y = y || 0;
        z = z || 0;
        let materials = [];
        let cubeGeometry = new THREE.CubeGeometry(len, len, len);
        let color = [Goldenrod, Firebrick, DeepSkyBlue, LimeGreen, White, Yellow];
        for (let i = 0; i < 6; i++) {
            let texture = new THREE.Texture(canvasTexture(color[i]), null);
            texture.needsUpdate = true;
            materials.push(new THREE.MeshBasicMaterial({map: texture, color: 0xffffff}));
        }
        simpleCube = new THREE.Mesh(cubeGeometry, materials);
        simpleCube.name = 'RubikCubeOne' + cubeIndex;
        simpleCube.position.x = x - len / 2;
        simpleCube.position.y = y - len / 2;
        simpleCube.position.z = z - len / 2;
        return simpleCube
    }

    function addRubikCube(size, len, x, y, z) {
        size = size || 3;//阶数
        len = len || 5;//每个方块的边长
        x = x || 0;//放置位置，整个魔方中心为准
        y = y || 0;
        z = z || 0;
        let fixedSize = size / 2;
        let cubeIndex = 0;
        for (let i = -fixedSize; i < fixedSize; i++) {
            for (let j = -fixedSize; j < fixedSize; j++) {
                for (let k = -fixedSize; k < fixedSize; k++) {
                    scene.add(buildSimpleCubeForRubikCube(len, x - len * i, y - len * j, z - len * k, cubeIndex))
                }
            }
        }
    }


    //增加平面几何形状
    function addPlaneGeometry(name) {
        let geometry = new THREE.PlaneGeometry(10, 5, 1, 1);
        let texture = THREE.TextureLoader.prototype.load("img/1.gif");

        let material = new THREE.MeshPhysicalMaterial({map: texture, side: THREE.DoubleSide});
        let mesh = new THREE.Mesh(geometry, material);
        mesh.name = name;
        mesh.rotation.x = -0.5 * Math.PI;
        mesh.castShadow = true;
        scene.add(mesh);
        return mesh;
    }

    //增加球形状
    function addSphereGeometry(name) {
        //设置球体的值
        // radius	        可选。此属性定义球体的半径。
        // widthSegments	可选。此属性定义球体竖直（维度）方向上的分段数。默认值是 8，最小值是 3
        // heightSegments	可选。此属性定义球体水平（经度）方向上的分段数。默认值是 6，最小值是 2
        // phiStart	        可选。此属性定义从 x 轴的什么地方开始绘制。取值范围是 0 到 2*π
        // phiLength	    可选。此属性定义从 phiStart 开始绘制多少。取值范围是 0 到 2*π
        // thetaStart	    可选。此属性定义从 y 轴的什么地方开始绘制。取值范围是 0 到 π
        // thetaLength	    可选。此属性定义从 thetaStart 开始绘制多少。取值范围是 0 到 π。一个 π 是整球，0.5*π只绘制上半球
        let sphere = new THREE.Mesh(
            new THREE.SphereGeometry(2, 30, 30),
            new THREE.MeshLambertMaterial({color: 0x123456})
        );
        sphere.geometry.verticesNeedUpdate = true;
        sphere.geometry.normalsNeedUpdate = true;
        sphere.name = name;
        sphere.castShadow = true;
        scene.add(sphere);
        return sphere;
    }

    //无光照效果，有颜色
    function addCubeBasic(name) {
        let cubeGeometry = new THREE.CubeGeometry(3, 3, 3);
        let color = [Goldenrod, Firebrick, DeepSkyBlue, LimeGreen, White, Yellow];
        for (let i = 0; i < cubeGeometry.faces.length;) {
            let faceColor = color[i / 2];
            cubeGeometry.faces[i].color.set(faceColor);//cube没面被分为两个三角形，共12个face，1、2为一面，3、4为一面，以此类推
            cubeGeometry.faces[++i].color.set(faceColor);
            i++;
        }
        let material = new THREE.MeshBasicMaterial({vertexColors: THREE.FaceColors,});
        let cube = new THREE.Mesh(cubeGeometry, material);
        cube.name = name;
        cube.castShadow = true;
        scene.add(cube);
        return cube;
    }

    //有光照效果，暗淡颜色
    function addCubeLambert(name) {
        let cubeGeometry = new THREE.CubeGeometry(3, 3, 3);
        let material = new THREE.MeshLambertMaterial({color: 0x00cc00});
        let cube = new THREE.Mesh(cubeGeometry, material);
        cube.name = name;
        cube.castShadow = true;
        scene.add(cube);
        return cube;
    }

    //有光照效果，金属类明亮颜色
    function addCubePhong(name) {
        let cubeGeometry = new THREE.CubeGeometry(3, 3, 3);
        let material = new THREE.MeshPhongMaterial({color: 0xcc0000});
        let cube = new THREE.Mesh(cubeGeometry, material);
        cube.name = name;
        cube.castShadow = true;
        scene.add(cube);
        return cube;
    }

    //钟表材质方块。动态材质
    function addCubeWithTexture(name) {
        let cubeGeometry = new THREE.CubeGeometry(10, 10, 10);

        let texture = new THREE.Texture(canvas);//材质
        let material = new THREE.MeshBasicMaterial({map: texture});

        let cube = new THREE.Mesh(cubeGeometry, material);
        cube.name = name;
        cube.castShadow = true;
        scene.add(cube);

        return cube;
    }


    //六面相同贴图
    function addCubeWithOnePic() {
        let geometry = new THREE.BoxGeometry(3, 3, 3);
        //二选一
        //1、使用TextureLoader加载图片作为素材------------start
        let texture = new THREE.TextureLoader().load('img/1.gif');
        //-----------------------------------------------end
        //2、使用canvas作为素材---------------------------start
        //let canvas = canvasTexture(null, 'img/1.gif');
        //let texture = new THREE.Texture(canvas);
        //texture.needsUpdate = true;
        //-----------------------------------------------end
        let material = new THREE.MeshBasicMaterial({map: texture});
        let box = new THREE.Mesh(geometry, material);
        scene.add(box);
        return box;
    }

    //六面不同贴图
    function addCubeWithDifferentPic() {
        let images = [
            'img/blocks/grass_side.png',
            'img/blocks/grass_side.png',
            'img/blocks/grass_top_green.png',
            'img/blocks/dirt.png',
            'img/blocks/grass_side.png',
            'img/blocks/grass_side.png',];
        let materials = [];
        let textureLoader = new THREE.TextureLoader();
        for (let i = 0; i < 6; ++i) {
            let texture = textureLoader.load(images[i]);
            texture.generateMipmaps = false;
            texture.magFilter = THREE.NearestFilter;
            texture.minFilter = THREE.NearestFilter;
            materials.push(new THREE.MeshLambertMaterial({
                map: texture,
                overdraw: true,
                fog: false
            }));
        }
        let cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), materials);
        scene.add(cube);
        return cube;
    }

    //增加天空盒
    function addSkyBox() {
        let backgroundType = 1;
        let textureCube = new THREE.CubeTextureLoader().load([
            'img/1.png',
            'img/2.png',
            'img/3.png',
            'img/4.png',
            'img/5.png',
            'img/6.png'
        ]);
        if (backgroundType === 1) {//使用场景背景添加
            scene.background = new THREE.Color(0x87CEEB);
        } else if (backgroundType === 2) {
            scene.background = textureCube
        } else {//使用盒子添加
            //着色器
            let cubeShader = THREE.ShaderLib["cube"];
            cubeShader.uniforms["tCube"].value = textureCube;
            let material = new THREE.ShaderMaterial({
                fragmentShader: cubeShader.fragmentShader,  //定义自己的片元着色器
                vertexShader: cubeShader.vertexShader,  //定义自己的顶点着色器
                uniforms: cubeShader.uniforms,  //给着色器传入uniform变量的值
                depthWrite: false,  //决定这个材质是否影响WebGL的深度缓存
                side: THREE.BackSide,  //侧面：反面
            });
            //创建方盒子
            let cubeWithPic = new THREE.Mesh(new THREE.CubeGeometry(1000000, 1000000, 1000000), material);
            scene.add(cubeWithPic);
        }
    }


    {
        // addRubikCube(1);
        let z = 40;

        function setPosition(obj) {
            z -= 10;
            obj.position.x = -40;
            obj.position.y = 3;
            obj.position.z = z;
        }

        let geometry = addPlaneGeometry("planeGeometry");
        setPosition(geometry);
        let sphereGeometry = addSphereGeometry("sphereGeometry");
        setPosition(sphereGeometry);
        let cubeLambert = addCubeLambert('cubeLambert');
        setPosition(cubeLambert);
        actionMove(cubeLambert, actions1).start();
        let cubeBasic = addCubeBasic("cubeBasic");
        setPosition(cubeBasic);
        let cubePhong = addCubePhong('cubePhong');
        setPosition(cubePhong);
        let cubeTime = addCubeWithTexture('cubeTime');  //scene.getObjectByName('cubeTime');
        setPosition(cubeTime);
        setDragFunction(cubeTime, true);
        let cubeWithOnePic = addCubeWithOnePic();
        setPosition(cubeWithOnePic);
        let cubeWithDifferentPic = addCubeWithDifferentPic();
        setPosition(cubeWithDifferentPic);
        addSkyBox();

        function autoRefresh() {
            actionRotateXYZ([cubeBasic]);
            cubeTime.material.map.needsUpdate = true;//材质刷新
        }
    }

    let lightValueChangeDirection = true;

    function changeLight() {
        light1.intensity = getAmbientLightIntensity();
        light2.intensity = getPointLightIntensity();
        light3.intensity = getDirectionalLightIntensity();
        if (lightValueChangeDirection) {
            if (lightValue >= lightLowIntensity - (lightHighIntensity - lightLowIntensity)) {
                lightValue -= 0.002;
            } else {
                lightValueChangeDirection = false;
            }
        } else {
            if (lightValue <= lightHighIntensity + (lightHighIntensity - lightLowIntensity)) {
                lightValue += 0.002;
            } else {
                if (lightValue > 1.5) {
                    lightValueChangeDirection = true;
                }
            }
        }
    }

    function refreshObj() {
        changeLight();
    }

    //草地块
    function addGrassCube(x, y, z) {
        let cubeSize = 1;
        let images = [
            'img/blocks/grass_side.png',
            'img/blocks/grass_side.png',
            'img/blocks/grass_top_green.png',
            'img/blocks/dirt.png',
            'img/blocks/grass_side.png',
            'img/blocks/grass_side.png',];
        let materials = [];
        let textureLoader = new THREE.TextureLoader();
        for (let i = 0; i < 6; ++i) {
            let texture = textureLoader.load(images[i]);
            texture.generateMipmaps = false;
            texture.magFilter = THREE.NearestFilter;
            texture.minFilter = THREE.NearestFilter;
            materials.push(new THREE.MeshLambertMaterial({
                map: texture,
                overdraw: true,
                fog: false,//当前材质是否收到全局雾化效果器影响
                // transparent:true,//透明
                // opacity:0.2,//透明度
            }));
        }
        let cube = new THREE.Mesh(new THREE.CubeGeometry(cubeSize, cubeSize, cubeSize), materials);
        cube.receiveShadow = cube.castShadow = true;
        cube.position.x = x + cubeSize / 2;
        cube.position.y = y + cubeSize / 2;
        cube.position.z = z + cubeSize / 2;
        cube.name = "GrassCube(" + x + "," + y + "," + z + ")";
        scene.add(cube);
    }

    (function addGrassCubes() {
        let grassCubePositionInfoArray = [
            [0, 0, 0],
            [1, 0, 0],
            [2, 0, 0],
            [0, 1, 0],
            [0, 1, 0],
        ];
        for (let grassCubePositionInfo of grassCubePositionInfoArray) {
            addGrassCube(grassCubePositionInfo[0], grassCubePositionInfo[1], grassCubePositionInfo[2])
        }
    })()

//自定义几何体（）
//     var vertices = [
//         new THREE.Vector3(0, 6, 0),
//         new THREE.Vector3(-1, 4, 0),
//         new THREE.Vector3(0, 4, 1),
//         new THREE.Vector3(1, 4, 0),
//         new THREE.Vector3(0, 4, -1),
//         new THREE.Vector3(0, 2, 0)
//     ];
//     var faces = [
//         new THREE.Face3(0, 1, 2),
//         new THREE.Face3(0, 2, 3),
//         new THREE.Face3(0, 3, 4),
//         new THREE.Face3(0, 4, 1),
//         new THREE.Face3(5, 2, 1),
//         new THREE.Face3(5, 3, 2),
//         new THREE.Face3(5, 4, 3),
//         new THREE.Face3(5, 1, 4),
//     ];
//     var geom = new THREE.Geometry();
//     geom.vertices = vertices;
//     geom.faces = faces;
//     geom.computeFaceNormals();//计算法向量 这决定了对光做出的反应
//
//     var materials = [
//         new THREE.MeshLambertMaterial({opacity: 0.8, color: 0x44e144, transparent: true}),//几何体面的材质
//         new THREE.MeshBasicMaterial({color: 0x008800, wireframe: true}),//一个几何体框架的材质
//     ];
//     var mesh1=new THREE.Mesh(geom, new THREE.MeshLambertMaterial({opacity: 0.8, color: 0x44e144, transparent: true}));
//     scene.add(mesh1);
    //以下创建多种材质（面线材质不同的几何体）
    // var mesh =SceneUtils.createMultiMaterialObject(geom, materials);//创建有多个材质的对象
    // mesh.name = '源';
    // mesh.children.forEach(function (e) {
    //     e.castShadow = false;
    // });
    // scene.add(mesh);
    // objects.push(mesh);


</script>
<script>
    window.onload = function () { //循环渲染动作
        (function render() {
            requestAnimationFrame(render);
            stats.update();
            TWEEN.update();
            renderer.render(scene, camera);
            autoRefresh();
            refreshObj();
        })();
    };

</script>
</body>
</html>
